package com.example.elastcisearch;

import lombok.SneakyThrows;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.ExtendedBounds;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.bucket.histogram.HistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedDateHistogram;
import org.elasticsearch.search.aggregations.bucket.range.Range;
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.Avg;
import org.elasticsearch.search.aggregations.metrics.Cardinality;
import org.elasticsearch.search.aggregations.metrics.Max;
import org.elasticsearch.search.aggregations.metrics.Min;
import org.elasticsearch.search.aggregations.metrics.Sum;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.Before;
import org.junit.Test;

import java.util.List;
import java.util.Map;

public class TestAggs {
    private RestHighLevelClient client = null;

    @Before
    public void before() {
        RestClientBuilder builder = RestClient.builder(new HttpHost("192.168.228.104", 9200, "http"));
        client = new RestHighLevelClient(builder);
    }
    
    

   /*
    
    GET /tvs/_search
    {
      "size": 0,
      "aggs": {
        "group_color": {
          "terms": {
            "field": "color"
          },
          "aggs": {
                "avg_color":{
                  "avg": {
                    "field": "price"
                  }
               }
          }
          
        }
    
      }
    }
    */
    @Test
    @SneakyThrows
    public void term() {
        SearchRequest request = new SearchRequest("tvs");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.size(0);
        builder.query(QueryBuilders.matchAllQuery());
        
        builder.aggregation(AggregationBuilders.terms("group_by_color").field("color"));

        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        Aggregations aggregations = response.getAggregations();
        Terms terms = aggregations.get("group_by_color");
        terms.getBuckets().forEach(e -> {
            System.out.println(e.getKeyAsString());
            System.out.println(e.getDocCount());
            System.out.println("**************");
        });

    }


    
    
    /*
    {
      "size": 0,
      "aggs": {
        "group_color": {
          "terms": {
            "field": "color"
          },
          "aggs": {
                "avg_color":{
                  "avg": {
                    "field": "price"
                  }
               },
               "sum_color":{
                  "sum": {
                    "field": "price"
                  }
               }
          }
          
        }
    
      }
    }     */
    
    
    @Test
    @SneakyThrows
    public void termAvg() {
        SearchRequest request = new SearchRequest("tvs");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.size(0);
        builder.query(QueryBuilders.matchAllQuery());

        TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("group_by_color").field("color");
        aggregationBuilder.subAggregation(AggregationBuilders.avg("avg_price").field("price"));
        builder.aggregation(aggregationBuilder);

        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        Aggregations aggregations = response.getAggregations();
        
        Terms terms = aggregations.get("group_by_color");

        List<? extends Terms.Bucket> buckets = terms.getBuckets();

        for (Terms.Bucket bucket : buckets) {
            System.out.println(bucket.getKeyAsString());
            System.out.println(bucket.getDocCount());
            Aggregations avgAggs = bucket.getAggregations();
            Avg avgPrice = avgAggs.get("avg_price");
            System.out.println(avgPrice.getValue());
            System.out.println("**************");
        }

    }

    
    
    
    /*  
    
    GET /tvs/_search
    {
      "size": 0,
      "aggs": {
        "group_color": {
          "terms": {
            "field": "color"
          },
          "aggs": {
            "avg_price":{ "avg": { "field": "price"}},
            "sum_price":{ "sum": { "field": "price"}},
            "max_price":{ "max": { "field": "price"}},
            "min_price":{ "min": { "field": "price"}}
          }
          
        }
    
      }
    }
    
     */
    @Test
    @SneakyThrows
    public void termAvg2() {
        SearchRequest request = new SearchRequest("tvs");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.size(0);
        builder.query(QueryBuilders.matchAllQuery());

        TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("group_by_color").field("color");
        aggregationBuilder.subAggregation(AggregationBuilders.avg("avg_price").field("price"));
        aggregationBuilder.subAggregation(AggregationBuilders.sum("sum_price").field("price"));
        aggregationBuilder.subAggregation(AggregationBuilders.max("max_price").field("price"));
        aggregationBuilder.subAggregation(AggregationBuilders.min("min_price").field("price"));
        
        builder.aggregation(aggregationBuilder);

        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        Aggregations aggregations = response.getAggregations();

        Terms terms = aggregations.get("group_by_color");

        List<? extends Terms.Bucket> buckets = terms.getBuckets();

        for (Terms.Bucket bucket : buckets) {
            System.out.println(bucket.getKeyAsString());
            System.out.println(bucket.getDocCount());
            
            Aggregations subAggs = bucket.getAggregations();
            Avg avg = subAggs.get("avg_price");
            Sum sum = subAggs.get("sum_price");
            Max max = subAggs.get("max_price");
            Min min = subAggs.get("min_price");
            
            System.out.println("avg" + avg.getValue());
            System.out.println("sum" + sum.getValue());
            System.out.println("max" + max.getValue());
            System.out.println("min" + min.getValue());
            System.out.println("**************");
        }

    }
    
    
    /*
    price每2000划分范围，算出每个区间的总和
    
    GET /tvs/_search
    {
      "size": 0,
      "aggs": {
        "histogram_price": {
          "histogram": {
            "field": "price",
            "interval": 2000
          },
          "aggs": {
                "sum_price":{
                  "sum": {
                    "field": "price"
                  }
               }
          }
          
        }
    
      }
    }
    */
    @SneakyThrows
    @Test
    public void testAggsAndHistogram() {
        SearchRequest request = new SearchRequest("tvs");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.size(0);
        builder.query(QueryBuilders.matchAllQuery());

        HistogramAggregationBuilder histogramAggregationBuilder = AggregationBuilders.histogram("histogram_price").field("price").interval(2000);
        histogramAggregationBuilder.subAggregation(AggregationBuilders.sum("sum_price").field("price"));

        builder.aggregation(histogramAggregationBuilder);

        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        Aggregations aggregations = response.getAggregations();
        
        Histogram histogram = aggregations.get("histogram_price");

        List<? extends Histogram.Bucket> buckets = histogram.getBuckets();

        for (Histogram.Bucket bucket : buckets) {

            System.out.println(bucket.getKeyAsString());
            System.out.println(bucket.getDocCount());

            Aggregations bucketAggregations = bucket.getAggregations();
            Sum sum = bucketAggregations.get("sum_price");
            System.out.println(sum.getValue());
            System.out.println("============");
        }
    }
    
    
    
    /*
    ## 每个季度销售总额
    GET /tvs/_search
    {
      "size": 0,
      "aggs": {
        "quarter_group": {
          "date_histogram": {
            "field": "date",
            "interval": "quarter",
            "format":"yyyy-MM-dd",
            "min_doc_count": 0,
            "extended_bounds": {
              "min": "2020-01-01",
              "max": "2020-12-01"
            }
          },
           "aggs":{
            "sum_price":{
              "sum": {
                "field": "price"
              }
            }
        }
        }
      }
    }
    */
    @Test
    @SneakyThrows
    public void dateHistogramAggs() {
        SearchRequest request = new SearchRequest("tvs");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.size(0);
        builder.query(QueryBuilders.matchAllQuery());

        DateHistogramAggregationBuilder dateHistogramAggregationBuilder = AggregationBuilders.dateHistogram("quarter_group")
                .field("date")
                .calendarInterval(DateHistogramInterval.QUARTER)
                .format("yyyy-MM-dd")
                .minDocCount(0)
                .extendedBounds(new ExtendedBounds("2020-01-01", "2020-12-31"));

        dateHistogramAggregationBuilder.subAggregation(AggregationBuilders.sum("sum_price").field("price"));

        builder.aggregation(dateHistogramAggregationBuilder);

        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        Aggregations aggregations = response.getAggregations();

        ParsedDateHistogram histogram = aggregations.get("quarter_group");

        List<? extends Histogram.Bucket> buckets = histogram.getBuckets();

        for (Histogram.Bucket bucket : buckets) {

            System.out.println(bucket.getKeyAsString());
            System.out.println(bucket.getDocCount());

            Aggregations bucketAggregations = bucket.getAggregations();
            Sum sum = bucketAggregations.get("sum_price");
            System.out.println(sum.getValue());
            System.out.println("============");
        }
        
    }


    /**去重后，计算总数
     * GET /shop/_search
     * {
     *   "aggs": {
     *     "aggbykeyword": {
     *       "cardinality": {
     *         "field": "keyword"
     *       }
     *     }
     *   }
     * }
     */
    @Test
    @SneakyThrows
    public void cardinalityAggs() {
        SearchRequest request = new SearchRequest("shop");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.aggregation(AggregationBuilders.cardinality("aggbykeyword").field("keyword"));
        request.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);
        Aggregations aggregations = searchResponse.getAggregations();
        Cardinality cardinality = aggregations.get("aggbykeyword");
        System.out.println(cardinality.getValue());

    }




        /*
         *
    # 数值范围求和 from包含 to不包含
    POST /order/_search
    {
      "aggs": {
        "rancebyid": {
          "range": {
            "field": "price",
            "ranges": [
              {
                "to": 4343
              },
              {
                "from": 4343,
                "to": 10236
              },
              {
                "from": 10236
              }
            ]
          }
        }
      }
    }


    POST /order/_search
    {
      "aggs": {
        "rancebyid": {
          "date_range": {
            "field": "price",
            "format": "yyyy-MM-dd",
            "ranges": [
              {
                "to": ""
              },
              {
                "from": "",
                "to": ""
              },
              {
                "from": ""
              }
            ]
          }
        }
      }

    }


    POST /order/_search
    {
      "aggs": {
        "rancebyid": {
          "ip_range": {
            "field": "ip",
            "ranges": [
              {
                "to": ""
              },
              {
                "from": "",
                "to": ""
              },
              {
                "from": ""
              }
            ]
          }
        }
      }

    }
         */

    @Test
    @SneakyThrows
    public void range() {
        SearchRequest request = new SearchRequest("order");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        RangeAggregationBuilder aggregationBuilder = AggregationBuilders.range("count_by_price").field("price")
                .addUnboundedTo(4343)
                .addRange(4343, 10236)
                .addUnboundedFrom(10236);
        builder.aggregation(aggregationBuilder);
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        Aggregations aggregations = response.getAggregations();
        Range range = aggregations.get("count_by_price");
        List<? extends Range.Bucket> buckets = range.getBuckets();
        for (Range.Bucket bucket : buckets) {
            System.out.println(bucket.getKeyAsString());
            System.out.println(bucket.getFrom());
            System.out.println(bucket.getTo());
            System.out.println(bucket.getDocCount());
            System.out.println("--------------");
        }
    }


}
